Many different computer system architectures exist. Examples of computer system architectures include Intel Architecture 32 by Intel Corporation and AMD64 by Advanced Micro Devices, Inc. (AMD). Computer system architectures are typically differentiated by their instruction set architecture, i.e., the native instructions supported by the central processing unit (CPU). Instructions written for a particular instruction set architecture are generally not directly compatible with other instruction set architectures.
Because different computer system architectures exist, software developers were historically required to rewrite software for each instruction set architecture. However, with time, technologies have evolved that help reduce the amount of effort required to port software from one instruction set architecture to another instruction set architecture. For example, the C programming language is relatively standard across different instruction set architecture implementations. However, software written in the C programming language must still be modified and recompiled for each instruction set architecture.
In more recent years, virtual machines have increased in popularity. Virtual machines are instruction set architecture-specific runtime environments designed to execute software compiled in an intermediate language. The intermediate language is relatively consistent across implementations of the virtual machine. Therefore, software that is compiled into the intermediate language can be distributed to any instruction set architecture for which the appropriate virtual machine has been implemented. Examples of virtual machines include the Java® Virtual Machine (JVM), the Microsoft .NET® Common Language Runtime (CLR), and variants thereof. Java® is a registered trademark of Sun Microsystems, Inc., located in Palo Alto, Calif. Microsoft .NET® is a registered trademark of Microsoft, Inc., located in Redmond, Wash.
Although virtual machines increase portability of software, there is computing overhead associated with using the intermediate language. Specifically, as instructions in the intermediate language are encountered at runtime, the instructions must be converted to native instructions by the virtual machine. In contrast, software compiled directly to native instructions does not incur this overhead.
To mitigate the overhead associated with using an intermediate language, some virtual machines use a just-in-time compiler. Typically, virtual machines that use runtime compilation operate as follows. An initial translation of the intermediate code into native instructions is performed using a relatively simple just-in-time compiler. The compilation is performed quickly, but often does not result in high-performance code. Therefore, the compiled code is instrumented during execution to provide information about “hot spots,” i.e., code paths that are executed frequently. Once identified, the “hot” code paths are recompiled by the virtual machine using a second, optimizing compiler. The optimizing compiler is slower than the just-in-time compiler that performed the initial translation, but generates higher quality (i.e., faster executing) native instructions.
Further, meta-circular virtual machines are virtual machines written in the same high-level language whose execution they support (e.g., a Java® virtual machine written in the Java® programming language). Developing a meta-circular virtual machine requires a static optimizing compiler to produce an efficient image of the virtual machine. The optimizing compiler used to build the meta-circular virtual machine may also be incorporated in the virtual machine image and used as a runtime optimizing compiler.
For a just-in-time compiler to function properly, native code templates must be present for each of the instructions in the intermediate language. These native code templates are typically created manually for each supported architecture. Therefore, porting a just-in-time compiler to a new instruction set architecture typically requires a large amount of manual effort. Because of this effort, many ports of virtual machines do not include a just-in-time compiler.